home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $Id: IOSerial.cpp 1.3 1995/09/26 16:48:58 olsen Exp olsen $
- **
- ** :ts=4
- */
-
- /*
- * Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
- *
- * Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
- * Erlangen-Nuremberg, Germany.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * Erlangen-Nuremberg, Germany.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software has not been validated by the ``Bundesamt fuer Zulassungen in
- * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
- * must not be used for accessing the BTX-Network of the Telekom in Germany.
- *
- * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
- * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
- * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
- */
-
- #include "IOSerial.hpp"
- #include "Control.h"
- #include "RawKeys.h"
- #include <string.h>
- #include <stdio.h>
-
- #define log(x) ;
-
- /******************** This is CONTROL SET C0 of CEPT ***********************/
-
- #define NOBLOCK 0 /* not receiving a block */
- #define TEXTBLOCK 1 /* normal text block */
- #define IMAGEBLOCK 2 /* transparent block */
- #define ERROR 0 /* status error */
-
- #define NUL 0x00 /* Null (data link) */
- #define SOH 0x01 /* start of heading (data link) */
- #define STX 0x02 /* start text (data link) */
- #define ETX 0x03 /* end text (data link) */
- #define EOT 0x04 /* end of transmission (data link) */
- #define ENQ 0x05 /* enquiry (data link) */
- #define ACK 0x06 /* acknowledge (data link) */
- #define ITB 0x07 /* end intermediate block (data link) */
- #define APB 0x08 /* active position back (control sequence) */
- #define APF 0x09 /* active position forward (control sequence) */
- #define APD 0x0a /* active position down (control sequence) */
- #define APU 0x0b /* active position up (control sequence) */
- #define CS 0x0c /* clear screen (control sequence) */
- #define APR 0x0d /* active position return (control sequence) */
- #define LS1 0x0e /* locking shift 1 (control sequence) */
- #define LS0 0x0f /* locking shift 0 (control sequence) */
- #define DLE 0x10 /* data link escape (data link) */
- #define CON 0x11 /* cursor on (control sequence) */
- #define RPT 0x12 /* repeat last character (control sequence) */
- #define INI 0x13 /* initiator '*' (btx special) */
- #define COF 0x14 /* cursor off (control sequence) */
- #define NAK 0x15 /* negative acknowledge (data link) */
- #define SYN 0x16 /* (data link) */
- #define ETB 0x17 /* end textblock (data link) */
- #define CAN 0x18 /* cancel,clear eol (control sequence) */
- #define SS2 0x19 /* single shift for G2 SET (control sequence) */
- #define DCT 0x1a /* (btx special) */
- #define ESC 0x1b /* escape (control sequence) */
- #define TER 0x1c /* terminator '#' (btx special) */
- #define SS3 0x1d /* single shift for G3 SET (control sequence) */
- #define APH 0x1e /* active position home (control sequence) */
- #define US 0x1f /* active position (x,y) (control sequence) */
-
- VOID IOSerial::Close(VOID)
- {
- if(Raw)
- {
- delete Raw;
-
- Raw = NULL;
- }
- }
-
- LONG IOSerial::Open(CONST STRPTR Channel,ULONG Unit,ULONG Baud,BOOL RTS_CTS)
- {
- LONG Error;
-
- Close();
-
- if(Raw = new IORawSerial)
- {
- if(Error = Raw->Open(Channel,Unit,Baud,RTS_CTS))
- {
- delete Raw;
-
- Raw = NULL;
- }
- }
- else
- Error = -1;
-
- return(Error);
- }
-
- LONG IOSerial::GetChar(LONG Timeout)
- {
- return((LONG)modeminput(Timeout));
- }
-
- VOID IOSerial::PutString(CONST STRPTR String,LONG Len)
- {
- if(Raw)
- {
- UBYTE *From,*s;
-
- if(Len < 0)
- Len = strlen(String);
-
- From = s = (UBYTE *)String;
-
- while(Len > 0)
- {
- switch(*s)
- {
- case 'Ä':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310A",2);
- break;
-
- case 'ä':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310a",2);
- break;
-
- case 'Ö':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310O",2);
- break;
-
- case 'ö':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310o",2);
- break;
-
- case 'Ü':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310U",2);
- break;
-
- case 'ü':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutString((CONST STRPTR)"\0310U",2);
- break;
-
- case KEY_CursorUp:
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(APU);
- break;
-
- case KEY_CursorDown:
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(APD);
- break;
-
- case '\b':
- case 127:
- case KEY_CursorLeft:
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(APB);
- break;
-
- case KEY_CursorRight:
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(APF);
- break;
-
- case KEY_Help:
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(APH);
- break;
-
- case '*':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
-
- Raw->PutChar(INI);
- break;
-
- case '#':
- case '\r':
- case '\n':
-
- if(From < s)
- {
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
-
- From = s + 1;
-
- Len -= (LONG)(s - From);
- }
-
- Raw->PutChar(TER);
- break;
-
- default:
-
- Len--;
- }
-
- s++;
- }
-
- if(From < s)
- Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
- }
- }
-
- LONG IOSerial::Waiting(VOID)
- {
- return(buffered + Raw->Waiting());
- }
-
- ULONG IOSerial::WaitMask(VOID)
- {
- return(Raw->WaitMask());
- }
-
- LONG IOSerial::getmodem(LONG Timeout)
- {
- return(Raw->GetChar(Timeout));
- }
-
- /* modeminput: this is data link layer (level 2) for getting blocks from
- * btx, crc check is done and characters are send to client
- */
-
- int IOSerial::modeminput(LONG Timeout)
- {
- LONG c1;
-
- if(buffered > 0)
- {
- buffered--;
-
- return((int)buffer[bufferindex++]);
- }
-
- for(;;)
- {
- c1 = getmodem(Timeout);
-
- if(c1 < 0)
- return(c1);
- else
- c = (UBYTE)c1;
-
- switch( block )
- {
- case TEXTBLOCK:
-
- calccrc(c);
-
- switch(c)
- {
- case DLE:
- case NAK:
- case ACK:
- case SOH:
-
- log(("Bad char:%x\n",c1));
- break;
-
- case STX:
-
- if(status == ERROR || status == ETB)
- {
- crc = 0;
- bufferlen = 0;
- status = EOT;
- }
-
- break;
-
- case EOT:
-
- ack01 = '0';
- block = NOBLOCK;
- break;
-
- case ITB:
- case ETB:
- case ETX:
-
- if(getcheck(Timeout) || status == ERROR)
- {
- bufferlen = 0;
- crc = 0;
- putmodem(NAK);
- status = ERROR;
-
- break;
- }
-
- status = c;
-
- if(c == ITB)
- putmodem(ACK);
- else
- {
- ack01 ^= 1;
- putmodem(DLE);
- putmodem(ack01);
-
- if(c == ETX)
- block = NOBLOCK; /* end of textblock */
- }
-
- if(bufferlen)
- {
- buffered = bufferlen - 1;
- bufferindex = 1;
-
- bufferlen = 0;
-
- return((int)buffer[0]);
- }
-
- break;
-
- case ENQ:
-
- switch( status )
- {
- case ERROR:
-
- putmodem(NAK);
- break;
-
- case EOT:
-
- putmodem(NAK);
- break;
-
- case ITB:
-
- putmodem(ACK);
- putmodem(NAK);
- break;
-
- case ETX:
- case ETB:
-
- putmodem(DLE);
- putmodem(ack01);
- putmodem(NAK);
- break;
- }
-
- break;
-
- default:
-
- if(bufferlen < BLOCK_BUFFER_SIZE-1)
- buffer[bufferlen++] = c;
- else
- log(("Blockbuffer overflow !\n"));
-
- break;
- }
-
- break;
-
- default: /* NOBLOCK */
-
- status = EOT;
-
- if(tfi)
- {
- if(tfi == SOH)
- {
- lastchar = c;
- tfi = ENQ;
- }
- else
- {
- if(c == ENQ)
- send_TFI();
-
- tfi=0;
- }
- }
-
- switch(c)
- {
- case EOT:
-
- ack01 = '0';
- break;
-
- case SOH:
-
- tfi = SOH;
-
- case STX:
-
- crc = 0;
- block = TEXTBLOCK;
- bufferlen = 0;
- break;
-
- default:
-
- return((int)c);
- }
-
- break;
- }
- }
- }
-
- void IOSerial::send_TFI()
- {
- putmodem(SOH);
- putmodem('@'); /* @ = intermediate blocksize */
- putmodem('5'); /* 5 = max. 256 bytes */
- putmodem(ETX);
- }
-
- void IOSerial::calccrc(unsigned int c)
- {
- register unsigned int cr = crc, ch = c;
- register unsigned int i,bit;
-
- for(i = 0 ; i < 8 ; i++) /* for all bits in character c */
- {
- bit = (cr & 1) ^ (ch & 1);
-
- cr >>= 1; /* bit 15 now cleared */
-
- if(bit) /* xor for polynom: x^16+x^15+x^2+x^0 */
- cr ^= 0xa001;
-
- ch >>= 1; /* shift character for next bit */
- }
-
- crc = (UWORD)cr;
- }
-
- /* get 2 bytes from modem and calccrc, return value is crc (should be 0 if
- * no crc error), during check handle socket inputs
- */
- UWORD IOSerial::getcheck(LONG Timeout)
- {
- LONG c;
- int i;
-
- for(i = 0 ; i < 2 ; i++)
- {
- c = getmodem(Timeout);
-
- if(c >= 0)
- calccrc((unsigned int)c);
- }
-
- if(crc)
- log(("CRC error %x\n",(int)crc));
-
- return(crc);
- }
-
- /******************************************************************************/
-
- IOSerial::IOSerial()
- {
- Raw = NULL;
-
- block = NOBLOCK;
- bufferlen = 0;
- tfi = 0;
- ack01 = '0';
- status = EOT;
- c = 0;
- crc = 0;
- lastchar = 0;
- buffered = 0;
- }
-
- IOSerial::~IOSerial()
- {
- Close();
- }
-